Scsi kernel-level drivers are actually software drivers in the sense that they do not communicate directly with a target (ie. no IO or memory register reads on the board). Rather, they request Scsi controller driver to do so on their behalf. They establish connection to the controller driver first and from then on, pass Scsi commands to the controller to be given to the target. In return, Scsi controller passes a driver the data received from a target.
The interface to the Scsi controller driver is provided through some arrays of funtion pointers. These arrays are:
scsi_info[]
scsi_alloc[]
scsi_command[]
scsi_free[]
Each entry in these arrays is a pointer to a function with 3 parameters.
(* scsi_xxx[])(adapter_no, target_id, lu_no)
driver_number:
SGI systems, depending on the platform, supports several different types of Controllers. So the index to these arrays is what is called "driver number". Driver number simply identifies the type of Controller driver we are using. The driver number itself is obtain through the array:
driver_number = scsi_driver_table[ adapter_no ].
As it is clear, we need to figure out 4 values before we establish any connection to the Scsi controller driver. The values adapter_no, target_id, lu_no are best obtained by scaning minor number of the driver (they have to be fed to the driver somehow). tpp.c uses the bits of minor number to figure these outs. Once the adapter_no is found, we can index to scsi_driver_table[] and figure out the driver_number.
Verifying the Target:
The device that is connected to the Scsi bus might not be the device that we can handle. Somehow we must verify that the device is indeed a DAT tape drive. Since we have figured out our driver_number, target_id, lu_no and adapter_no, we can ask the Scsi controller to issue an Inquiry command to the target on our behalf and pass us back the data:
struct scsi_target_info *info;
info = (*scsi_info[driver])( adapter, target, lu );
Now, we must scan the Inquiry data (in info->si_inq) according to the DAT drive specs and make sure the device is a DAT tape.
Establishing Connection:
Once we have verified that the drive is a DAT tape, we can go ahead and establish a logical connection to it through Scsi Controller:
err = ( *scsi_alloc[driver])(adapter, target, lu,
SCSIALLOC_EXCLUSIVE, NULL );
Issuing Command:
We can issue Scsi command by filling a scsi_request structure and passing it's address to the Controller's routine:
(*scsi_command[driver])(req);
See sys/scsi.h for description of scsi_request fields and also see how tpp handles them.
You should have the following files:
README This file in "ascii-text" form Makefile Compiles/links all programs including driver tpp.c Source code for the driver tppkern.h Kernel driver's header file tppuser.h Application interface header file tpp.master Master file for the driver tpp.sm System file for the driver getInfo.c Program to get tape information and display initTape.c Program to initialize a tape tapeFs.c Simple tape file system
You MUST study your system's /var/sysgen/Makefile.kernio Makefile which contains the kernel compiler flags--specifically for your system--so that your driver is compiled with the same flags as the rest of your system's kernel. Replace the CFLAGS definition in the Makefile with the appropriate one from your /var/sysgen/Makefile.kernio file.
Select a Major number by consulting with sys/major.h. For example, I have selected 71 for my machine. Then construct the proper minor number for tape's special file: The bits of a minor number are as follow:
Bits 0 Controller Number ( 0 or 1 ) 1 Adapter Number ( 0 or 1 - same as Controller ) 2-5 Target ID ( 0 - 0xffff ) 6-9 Lu ID ( 0 - 0xffff )Now create the special files /dev/tppdev0 (Scsi controller 0) and /dev/tppdev1 (Scsi controller 1) by entering:
mknod /dev/tppdev cFor example, on my machine (Indogo2) they are:
crw-rw-rw- 1 root sys 71, 8 May 9 16:21 /dev/tppdev0 crw-rw-rw- 1 root sys 71, 19 May 9 16:30 /dev/tppdev1To find out the Target ID, do a 'hinv' and see what the target Id of the DAT drive is. Now do:
cp tpp.o /var/sysgen/boot cp tpp.master /var/sysgen/master.d/tpp cp tpp.sm /var/sysgen/system autoconfig -f -vIf you have compiled the driver as a loadable module, you do not need to reconfigure the kernel. Simply load the driver by entring either:
make loador
ml ld -c /var/sysgen/boot/tpp.o -p tpp_ -cYou are ready to run the test program, including the tapeFs.